package ru.ifmo.network.skype.network;

import ru.ifmo.network.skype.network.data.MessageType;
import ru.ifmo.network.skype.network.data.UserAddress;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.List;

/**
 * @author avhaliullin
 */
public class UDPMessageReceiver implements Runnable, MessageHandler {
    private final int bufferSize;
    private final List<MessageHandler> handlers;
    private final DatagramSocket socket;

    public UDPMessageReceiver(int bufferSize, List<MessageHandler> handlers, int port) throws SocketException {
        this.bufferSize = bufferSize;
        this.handlers = handlers;
        socket = new DatagramSocket(port);
    }

    private void handle(byte[] buff, UserAddress address) throws IOException, ClassNotFoundException {
        ObjectInput is = new ObjectInputStream(new ByteArrayInputStream(buff));
        Integer typeInt = (Integer) is.readObject();
        MessageType type = MessageType.getByValue(typeInt);
        switch (type) {
            case AUDIO_DATA: {
                Long serialId = (Long) is.readObject();
                byte[] data = (byte[]) is.readObject();
                handleAudio(address, serialId, data);
            }
            break;
            case SECURE: {
                long gid = (Long) is.readObject();
                byte[] data = (byte[]) is.readObject();
                handleGroup(address, gid, data);
            }
            break;
            case HELLO: {
                handleGoodbye(address);
            }
            break;
            case GOODBYE: {
                handleGoodbye(address);
            }
        }
    }

    public void run() {
        while (!Thread.interrupted()) {
            byte[] buf = new byte[bufferSize * 2];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            try {
                socket.receive(packet);
                handle(buf, new UserAddress(packet.getAddress()));
            } catch (IOException | ClassNotFoundException | RuntimeException e) {
                e.printStackTrace();
            }

        }
    }

    @Override
    public void handleHello(UserAddress userAddress) {
        for (MessageHandler handler : handlers) {
            handler.handleHello(userAddress);
        }
    }

    @Override
    public void handleGoodbye(UserAddress userAddress) {
        for (MessageHandler handler : handlers) {
            handler.handleGoodbye(userAddress);
        }
    }

    @Override
    public void handleAudio(UserAddress userAddress, long serialId, byte[] data) {
        for (MessageHandler handler : handlers) {
            handler.handleAudio(userAddress, serialId, data);
        }
    }

    @Override
    public void handleGroup(UserAddress userAddress, long groupId, byte[] data) {
        for (MessageHandler handler : handlers) {
            handler.handleGroup(userAddress, groupId, data);
        }
    }

}
